#include "pcap.h"
#include "global.h"

void check_requirements(void){
	if (getuid() != 0){
		fprintf(stderr, "Seems that you aren't root user !\n");
		exit(EXIT_FAILURE);
	}
	return;
}

void getDevice(struct devInfo *myDevInfo){
	char 	*dev, errbuf[PCAP_ERRBUF_SIZE];
	bpf_u_int32 	mask;		/* Masque réseau */
	bpf_u_int32 	net;		/* Adresse IP */

	dev = pcap_lookupdev(errbuf);
	if (dev == NULL) {
		fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
		exit(EXIT_FAILURE);
	}
	if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
		fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
		net = 0;
		mask = 0;
	}
	myDevInfo->mask = mask;
	myDevInfo->net = net;
	myDevInfo->dev = dev;
	return;
}

#ifdef DEBUG
void displayInformationDevice(struct devInfo *myDevInfo){
	struct 	in_addr 	ip,mask;

	ip.s_addr = myDevInfo->net;
	mask.s_addr = myDevInfo->mask;
	printf("DEBUG:\tDevice = %s\n", myDevInfo->dev);
	printf("DEBUG:\tIPv4   = %s\n", inet_ntoa(ip));
	printf("DEBUG:\tMask   = %s\n", inet_ntoa(mask));
	return;
}
#endif

double conv2( uint16_t* pr )
{
    uint16_t    pa[4];
    int         i;

    for(i=0;i<4;i++) pa[i] = pr[i];

    return *((double*)pa);
}

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
	/* declare pointers to packet headers */
	const struct sniff_ethernet *ethernet;  /* The ethernet header [1] */
	const struct sniff_ip *ip;              /* The IP header */
	const struct sniff_tcp *tcp;            /* The TCP header */
	const char *payload;                    /* Packet payload */

	/* Compute mask for post visualisation */
	struct in_addr maskVisu;
	struct in_addr ipVisu;
	struct in_addr num;
	maskVisu.s_addr = inet_addr("0.0.0.255");

	int size_ip;
	int size_tcp;
	int size_payload;

	double srcport, dstport;


	/* define ethernet header */
	ethernet = (struct sniff_ethernet*)(packet);

	
	/* define/compute ip header offset */
	ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
	size_ip = IP_HL(ip)*4;
	if (size_ip < 20) {
		printf("   * Invalid IP header length: %u bytes\n", size_ip);
		return;
	}

	switch(ip->ip_p) {
		case IPPROTO_TCP:
			/* define/compute tcp header offset */
			tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
			size_tcp = TH_OFF(tcp)*4;
			if (size_tcp < 20) {
				printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
				return;
			}
			ipVisu.s_addr = ip->ip_dst.s_addr & maskVisu.s_addr;
				//printf("(%d,%i,%d)\n",ntohl(ipVisu.s_addr), ntohs(tcp->th_sport), ntohs(tcp->th_dport));
				n3d_add(ipVisu, ntohs(tcp->th_sport), ntohs(tcp->th_dport));
				//dpl_point(ntohl(ipVisu.s_addr)-127, ntohs(tcp->th_sport)-32768, ntohs(tcp->th_dport)-32768);

			
			break;
		case IPPROTO_UDP:
			printf("   Protocol: UDP\n");
			return;
		case IPPROTO_ICMP:
			printf("   Protocol: ICMP\n");
			return;
		case IPPROTO_IP:
			printf("   Protocol: IP\n");
			return;
		default:
			printf("   Protocol: unknown\n");
			return;
	}

	return;
}

void init_pcap(void){
	pcap_t 	* handle;		//Handle de capture
	struct bpf_program fp;
	char	* device;		//Périphérique pour sniffer
	struct devInfo myDevInfo;
	char errbuf[PCAP_ERRBUF_SIZE];
	int num_packets = 1000000;
  char filtre[28];

  strcat(filtre, (char*)"tcp and host ");

	getDevice(&myDevInfo);
#ifdef DEBUG
	displayInformationDevice(&myDevInfo); // affiche ip/mask/peripherique
#endif
	handle = pcap_open_live(myDevInfo.dev, BUFSIZ, 1, 0, errbuf);
	if (handle == NULL) {
		fprintf(stderr, "Couldn't open device %s: %s\n", "eth0", errbuf);
		exit(EXIT_FAILURE);
	}
  strcat(filtre, net_addr);
	if (pcap_compile(handle, &fp, FILTRE, 0, myDevInfo.net) == -1){
		fprintf(stderr, "Couldn't parse filter %s: %s\n", FILTRE, pcap_geterr(handle));
		exit(EXIT_FAILURE);
	}
	if (pcap_setfilter(handle, &fp) == -1) {
		fprintf(stderr, "Couldn't install filter %s: %s\n", FILTRE, pcap_geterr(handle));
		exit(EXIT_FAILURE);
	}
	pcap_loop(handle, num_packets, got_packet, NULL);
	pcap_freecode(&fp);
	pcap_close(handle);

}

